/**
 * 
 */
package martinhynar.blog;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Logger;

import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;

import martinhynar.blog.limitedservice.v1_0.LimitedService;
import martinhynar.blog.limitedservice.v1_0.LimitedService_Service;

public class LimitedServiceClient implements LimitedServiceClientInterface {

	private static final Logger LOG = Logger
			.getLogger(LimitedServiceClient.class.getName());

	private LimitedService getService() throws Exception {
		// Get a handle to web service client interface
		LimitedService_Service service = new LimitedService_Service(new URL(
				"resource://LimitedService.wsdl"), new QName(
				"urn:martinhynar:blog:limitedservice:v1_0", "LimitedService"));
		LimitedService limitedService = service.getLimitedServiceSessionPort();

		String endpointAddress;
		String server = "localhost";
		endpointAddress = "http://" + server
				+ ":8080/webservice/LimitedService";
		LOG.info("Using endpoint address: " + endpointAddress);

		((BindingProvider) limitedService).getRequestContext().put(
				BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointAddress);

		return limitedService;
	}

	/**
	 * Makes the WS call.
	 */
	private void limitedServiceRequest(LimitedService limitedService,
			String parameter) {
		String response = limitedService.limitedServiceRequest(parameter);
		LOG.info(String.format(
				"Contacted limited service. Sent \"%s\" received \"%s\".",
				parameter, response));

	}

	@Override
	public void launchRequests(Integer amount) {
		try {
			List<RequestThread> tasks = new ArrayList<RequestThread>(amount);
			for (int i = 0; i < amount; i++) {
				tasks.add(new RequestThread(new LimitedServiceClient()));
			}

			ExecutorService exs = Executors.newFixedThreadPool(amount);
			exs.invokeAll(tasks);
			LOG.info(String.format(
					"Successfuly executed %d parallel requests.", amount));

		} catch (Exception e) {
			LOG.warning(String.format(
					"Exception occured while contacting limited service: %s",
					e.getMessage()));
		}
	}

	/**
	 * Class representing callable task for executor service. It makes the
	 * actual request.
	 */
	private static class RequestThread implements Callable<Void> {

		private final LimitedServiceClient client;

		public RequestThread(LimitedServiceClient client) {
			this.client = client;
		}

		@Override
		public Void call() throws Exception {
			LimitedService service = client.getService();
			client.limitedServiceRequest(service, "abc");
			return null;
		}

	}

}